from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import User
import re
from rest_framework_simplejwt.tokens import AccessToken
from django.core.cache import cache
from django.conf import settings


class CommonLoginSerializer:
    def _get_user(self, attrs):
        raise Exception('这个方法必须被重写')

    def _pre_data(self, token, user):
        host = self.context['Host']
        self.context['token'] = token
        self.context['username'] = user.username
        self.context['icon'] = 'http://' + host + '/media/' + str(user.icon)

    def validate(self, attrs):
        user = self._get_user(attrs)
        token = str(AccessToken.for_user(user))
        self._pre_data(token, user)
        return attrs


class LoginSerializer(CommonLoginSerializer, serializers.ModelSerializer):
    username = serializers.CharField()

    class Meta:
        model = User
        fields = ['username', 'password', 'icon']
        extra_kwargs = {
            'icon': {
                'read_only': True
            },
            'password': {
                'write_only': True
            }
        }

    def _get_user(self, attrs):
        username = attrs.get('username')
        if re.match(r'^1[3-9][0-9]{9}$', username):
            user = User.objects.filter(mobile=username).first()
        elif re.match(r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,4})+$', username):
            user = User.objects.filter(email=username).first()
        else:
            user = User.objects.filter(username=username).first()

        if not user:
            raise ValidationError({'username': '用户名错误'})
        password = attrs.get('password')
        if not user.check_password(password):
            raise ValidationError({'password': '密码错误'})
        return user


class SMSLoginSerializer(CommonLoginSerializer, serializers.Serializer):
    code = serializers.CharField()
    mobile = serializers.CharField()

    def _get_user(self, attrs):
        code = attrs.get('code')
        mobile = attrs.get('mobile')
        old_code = cache.get(f'cache_code_{mobile}')
        assert old_code == code or (settings.DEBUG and code == '8888'),'验证码错误'
        user = User.objects.filter(mobile=mobile).first()
        assert user, ValidationError('该手机号用户没注册')
        return user


class RegisterSerializer(serializers.ModelSerializer):
    # 校验和保存(create)
    code = serializers.CharField()

    class Meta:
        model = User
        fields = ['mobile', 'password', 'code']

    def validate(self, attrs):
        code = attrs.pop('code')
        mobile = attrs.get('mobile')
        old_code = cache.get(f'cache_code_{mobile}')
        assert old_code == code or (settings.DEBUG and code == '8888'), '验证码错误'
        attrs['username'] = 'user_' + mobile[-4:]
        return attrs

    def create(self, validated_data):
        user = User.objects.create_user(**validated_data)
        return user
